12.5.5 いつバッファ付きのチャネルを使うべきか
バッファ付きのチャネルを正しく使うには、バッファが一杯になった場合(書き込み側のゴルーチンがあるが読み込み側のゴルーチンを持っている状態)にどう対処するかを記述しなければならない
いつバッファ付きのチャネルを使うべきかは以下
起動した一群のゴルーチンからデータを集めたい場合
バッファがないと、デッドロックになる可能性がある
code:go
package main
import (
"fmt"
"math/rand"
"time"
)
func processChannel(ch chan int) []int {
const maxConc = 10
results := make(chan int, maxConc)
for i := 0; i < maxConc; i++ {
go func() {
v := <-ch
results <- process(v)
}()
}
fmt.Println("ゴルーチン 起動完了")
var out []int // intのスライス
for i := 0; i < maxConc; i++ {
out = append(out, <-results) // 結果を受け取って後ろに追加
}
return out
}
func process(v int) int {
returnVal := v * v
// rand.Seed(time.Now().UnixNano()) // Go 1.20から不要になった(乱数のシードの設定)
sleepSec := rand.Intn(3) // 0以上3未満の整数を戻す
fmt.Println("process:", v, returnVal, sleepSec)
time.Sleep(time.Duration(sleepSec) * time.Second)
return returnVal
}
func main() {
ch := make(chan int)
var result []int
go func() { // 処理してもらう数値をchに入れる
for i := 0; i < 100; i++ {
ch <- i
}
}()
result = processChannel(ch)
fmt.Printf("result: %d\n", result)
}
並行実行の並行度を制限したい場合